/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include <物体/S_物体.h>
#include <面/Mesh.h>
//#include "intern/模型/S_模型.h"
//#include "intern/发射体/S_发射体.h"
#include "S_摄像机.h"


void f_设置物体物理属性(S_物体* obj);
/*void f_创建刚体(S_物体* obj);
void f_创建柔体(S_物体* obj);
void f_创建布料(S_物体* obj);*/


S_物体*		f_ob_创建物体(E_物体类型 type, S_物体* froObj, S_设备环境 ctx);
//S_物体*		f_ob_创建物体(S_设备环境& ctx, E_物体类型 type, void* data);
S_物体*		f_ob_创建物体(S_设备环境& ctx, E_物体类型 type);
S_物体*		f_ob_创建物体实例(S_物体* 父物体, uint32 loc);
S_物体*		f_ob_创建物体实例(S_物体* froObj);
S_物体*		f_ob_添加实例(S_物体* 父物体, uint32 实例ID = -1);
S_物体*     f_ob_创建骨骼(S_物体* 父物体);
//S_物体*     f_ob_创建骨骼(S_设备环境& ctx);
S_物体*     f_ob_创建灯光(S_设备环境& ctx, E_物体类型 type);
void		f_ob_销毁物体(S_物体* 物体);
void		f_ob_改变物体类型(S_物体* ob, E_物体类型 type, S_设备环境& ctx);



S_物体*		f_创建BOX物体(const vec3& size, S_设备环境 ctx, bool 三角化 = true, E_绘图API engineType = E_绘图API::E_Vulkan);
S_物体*		f_创建圆柱物体(const vec3& 高_半径, uint32 细分, S_设备环境 ctx, bool 三角化 = true, E_绘图API engineType = E_绘图API::E_Vulkan);
S_物体*		f_创建球体物体(const float32 半径, uvec2 细分, S_设备环境 ctx, bool 三角化=true, E_绘图API engineType = E_绘图API::E_Vulkan);
//S_物体*	f_get物体(uint32 key);
void		f_ob_create骨骼虚拟体网格(S_设备环境& ctx, S_物体* 骨骼, S_物体* 骨节);

void		f_ob_构建骨骼虚拟体实例ID(S_物体* ob, uint32& d);
void		f_ob_构建骨骼(S_物体* ob, S_物体* 骨骼物体, S_物体* 骨节物体, S_物体* 骨骼辅助虚拟物体);
void		f_ob_绑定网格骨骼(S_物体* ob, S_物体* bonse, uint32 mesh_loc);
void		f_创建发射体(S_物体* froObj);


S_摄像机*	f_创建摄像机(S_设备环境 ctx, E_绘图API engineType = E_绘图API::E_Vulkan);
void		f_ob_销毁摄像机(S_摄像机* camera);



void		f_ob_link物体数据(S_物体* ob, S_物体* froObj);
S_物体*		f_ob_copy物体数据(S_设备环境& ctx, S_物体* froObj);
void		f_ob_set数据槽数量(S_物体* Obj, uint32 num);
void		f_ob_set数据(S_物体* Obj, void* data, uint8 loc = 0);
void		f_ob_set实例数量(S_物体* Ob, uint32 num, uint32 deviceID = 0);
void		f_ob_fill实例(S_物体* Ob, uint32 num);
void		f_ob_set为实例(S_物体* Obj);
void		f_ob_set物体数据可视(S_物体* Obj, uint8 loc, bool 是否可视);
//void		f_ob_重置顶点数量(S_物体* Obj, uint32 num);
void		f_ob_set线宽(S_物体* Obj, float32 h, uint8 loc = 0);
void		f_ob_set细分(S_物体* Obj, uint32 次数, uint8 loc = 0);
void		f_ob_set网格可视(S_物体* ob, bool show, uint8 loc = 0);

void		f_ob_set材质(S_物体* Obj, S_材质* mat, uint8 loc = 0);
void		f_ob_set矩阵(S_物体* Obj, C_Mat44& mat);
void		f_ob_set矩阵(S_物体* Obj, const Mat44f& mat, uint32 实例ID = 0);
void		f_ob_set颜色2(S_物体* Obj, S_RGBA8UI color, uint32 offset, uint8 槽 = 0);
void		f_set粒子数量(S_物体* Obj, uint32 num);
void		f_set粒子位置(S_物体* Obj, const vec3* l, uint32 num);
void		f_set粒子速度(S_物体* Obj, const vec3* v, uint32 num);
void		f_set粒子旋转(S_物体* Obj, const vec3* r, uint32 num);
void		f_set粒子大小(S_物体* Obj, const vec3* s, uint32 num);
void		f_set粒子渲染物体(S_物体* Obj, E_粒子绘制类型 绘制类型);
void		f_ob_set颜色(S_物体* Obj, const S_RGBA8UI& color, uint32 槽);
//void		f_ob_创建实例Data(S_物体* Obj, void* data, uint8 loc);
S_物体*		f_ob_copy(S_设备环境& ctx, S_物体* Obj, bool 链接 = true);
void*		f_ob_copyData(S_物体* 目标物体, S_物体* 源物体, bool 链接 = true);



S_Mesh*		f_ob_fromTranformMesh(S_物体* froObj, uint32 loc = 0);

Inline S_Mesh* f_ob_Mesh(S_物体* ob, uint32 id = 0) {
	return (S_Mesh*)(ob->m_Data[id]);
}


S_LigthParallel* f_ob_fromParallelLigth(S_物体* froObj);
S_LigthSpot* f_ob_fromLigthSpot(S_物体* froObj);
S_LigthPoint* f_ob_fromLigthPoint(S_物体* froObj);
S_LigthArea* f_ob_fromAreaLigth(S_物体* froObj);
S_灯光场景数据* f_ob_fromLigthSceneData(S_物体* froObj);

Inline uint32	f_ob_get数量层数量(S_物体* ob) {
	return ob->m_DataNum;
}

uint32		f_ob_get实例数量(S_物体* Obj);
uint32		f_ob_get顶点数量(S_物体* Obj);
float32		f_ob_get最大半径(S_物体* Obj);
S_VecSphere	f_ob_get范围(S_物体* Obj);
S_物体*		f_ob_get子对象(S_物体* Obj, uint32 offset);
S_物体*		f_ob_get实例ID对象(S_物体* Obj, uint32 ID);
S_物体*     f_ob_get父变换对象(S_物体* Obj);
vec3		f_ob_get全局坐标(S_物体* Obj, uint32 ID);

Mat44f		f_ob_get变换矩阵(S_物体* Ob);
//Mat44f		f_ob_get实例变换矩阵(S_物体* Ob, uint32 ID);

S_物体*		f_ob_from实例对象取父对象(S_物体* Obj);
E_物体类型	f_ob_get可视对象类型(S_物体* Obj);
uint64		f_ob_get子物体数量(S_物体* Ob, bool 包括子集 = false);
S_物体*     f_ob_以类型查找子物体(S_物体* ob, E_物体类型 type);


uint32		f_ob_add子物体(S_物体* 父, S_物体* 子, uint32 loc = 0xffffffff);
void		f_ob_add实例物体(S_物体* 父, S_物体* 子物体, uint32 loc = 0xffffffff);
void		f_ob_ins实例物体(S_物体* 父, uint32 实例ID, uint32 loc = 0xffffffff);
void		f_ob_set实例物体(S_物体* 父, S_物体* 子, uint32 loc = 0xffffffff);
void		f_ob_clear子物体(S_物体* 父, uint64 s = 0, uint64 e = -1);
void		f_ob_销毁子物体(S_物体* 父, uint64 s = 0, uint64 e = -1);

Inline void f_ob_清除子物体(S_物体* 父) {
	父->m_子物体.clear();
	if (父->m_变换矩阵.m_Buf) {
		f_ob_清除矩阵(父);
	}
}

void		f_ob_setPos(S_物体* ob, const vec3& loc, uint32 id = 0);

void		f_ob_构建光追实例加速结构(S_物体* ob, S_设备环境& ctx);



void f_ob_Load物体(S_物体* ob, FILE* f);
void f_ob_Save物体(S_物体* ob, FILE* f);

const uint8* f_ob_Load物体(S_物体* ob, const uint8* 块);
void f_ob_Save物体(S_物体* ob, S_UI8Array* 块);

const uint8* f_ob_Load多物体(S_OBArray* obs, const uint8* 块);
void f_ob_Save多物体(const S_OBArray* obs, S_UI8Array* 块);


void f_ob_Load多物体(S_OBArray* objs, FILE* f, S_设备环境& ctx, bool 数据 = false);
void f_ob_Save多物体(const S_OBArray* objs, FILE* f, bool 数据 = false);


void f_load物体(FILE* f, S_物体* obj);
void f_save物体(FILE* f, S_物体* obj);

std::vector<S_物体*> f_load多物体(FILE* f, S_设备环境 ctx);
void f_save多物体(FILE* f, const std::vector<S_物体*>& objs);


void f_ob_loadFBX(std::vector<S_物体*>& objs, std::string& path, S_设备环境& ctx);
S_物体* f_ob_loadOBJ(const std::string& path, S_设备环境 ctx);










/****************************** 物体变换操作 ********************************/
vec3 f_obj_get方向(S_物体* obj, E_轴向 轴向);
vec3 f_ob_get中心(const std::vector<S_物体*>& obs);

void f_ob_增量移动(S_物体* obj, vec3 距离);
void f_ob_set缩放(S_物体* obj, const vec3& 缩放);




float32 f_get相机到视点距离(S_摄像机* camera);
//方向是从摄像机位置到视点
//vec3	f_camera_get视线向量(S_摄像机* camera);
vec3	f_camera_get眼睛位置(S_摄像机* camera);
vec3	f_get相机变换后位置(S_摄像机* camera);
void	f_set摄像机视点位置(S_摄像机* camera, vec3 pos);
void	f_set摄像机视点移动到偏移点(S_摄像机* camera);
void	f_camera_set偏移视点(S_摄像机* camera, const vec3& pos);
vec3	f_camera_get相机视线平移方向(const S_摄像机& camera, vec3& H, vec3& V);
vec3	f_camera_get视线向量(S_摄像机* camera);
vec3    f_camera_计算摄像机以角度缩放大小(S_摄像机* camera);



/***************************** 扩展物体参数设置 *****************************/

void f_ob_set域(S_物体* Obj, S_DomProp& 域绘制参数, uint8 loc = 0);




